//按照国际象棋的规则，皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 
//
// n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上，并且使皇后彼此之间不能相互攻击。 
//
// 给你一个整数 n ，返回所有不同的 n 皇后问题 的解决方案。 
//
// 
// 
// 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案，该方案中 'Q' 和 '.' 分别代表了皇后和空位。 
// 
// 
//
// 
//
// 示例 1： 
// 
// 
//输入：n = 4
//输出：[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
//解释：如上图所示，4 皇后问题存在两个不同的解法。
// 
//
// 示例 2： 
//
// 
//输入：n = 1
//输出：[["Q"]]
// 
//
// 
//
// 提示： 
//
// 
// 1 <= n <= 9 
// 
//
// Related Topics 数组 回溯 👍 2095 👎 0

package leetcode.editor.cn;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

//java:N 皇后
public class Q0051NQueens {
    public static void main(String[] args){
        Solution solution = new Q0051NQueens().new Solution();
    }
    //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    List<List<String>> resList = new ArrayList<>();
    public List<List<String>> solveNQueens(int n) {
        char[][] boards = new char[n][n];
        for (int i = 0; i < n; i++) {
            Arrays.fill(boards[i], '.');
        }
        backtracking(boards, 0);
        return resList;
    }

    public void backtracking(char[][] boards, int row) {
        if (row == boards.length) {
            resList.add(Array2List(boards));
            return;
        }

        // startIndex 从0开始，每一层从头开始遍历
        // 每一层，遍历每一行的所有元素
        for (int j = 0; j < boards.length; j++) {
            if (isValid(boards, j, row)) {
                boards[row][j] = 'Q';
                // 向下遍历每一行的元素
                backtracking(boards, row + 1);
                boards[row][j] = '.';
            }
        }
    }

    public boolean isValid(char[][] boards, int col, int row) {
        // 剪枝操作，都只需要向上操作，向下的还没有加入进来
        // 横向
        for (int j = 0; j < col; j++) {
            if (boards[row][j] == 'Q') {
                return false;
            }
        }
        // 竖向
        for (int i = 0; i < row; i++) {
            if (boards[i][col] == 'Q') {
                return false;
            }
        }
        //45度斜向, 不可以这样写，不一定是中间元素
//        for (int i = 0, j = 0; i < row && j < col; i++, j++) {
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
            if (boards[i][j] == 'Q') {
                return false;
            }
        }

        // 135度斜向，不可以这样写，不一定是中间元素
//        for (int i = 0, j = boards.length - 1; i < row && j > col; i++, j--) {
        for (int i = row - 1, j = col + 1; i >=0 && j < boards.length; i--, j++) {
            if (boards[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }

    public List<String> Array2List(char[][] boards) {
        List<String> pathList = new ArrayList<>();
        for (int i = 0; i < boards.length; i++) {
            pathList.add(new String(boards[i]));
        }
        return pathList;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}